package com.bocai.grainshop.order.config;

import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;


import javax.annotation.PostConstruct;

public class RabbitTemplateConfig {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    //定制RabbitTemplate

    //步骤一: 定制消息抵达rabbit服务器回调
    //1.spring.rabbitmq.publisher-confirm-type=correlated
    //2.设置确认回调

    //步骤二: 定制消息从交换机抵达队列回调
    //1.#开启交换机抵达队列事务
    //spring.rabbitmq.publisher-returns=true
    //#只要成功抵达，已异步发送优先回调我们这个returnconfirm
    //spring.rabbitmq.template.mandatory=true
    //2.设置确认回调

    //步骤三: 定制消息从交换机抵达消费者(保证每个消息被正确消费，此时才可broker删除这个消息)
    //1.默认是自动确认的，只要消息接受到，客服端会自动确认，服务端就会移除这个消息
    // 问题:
    //    我们收到很多消息，自动回复给服务器ack,只有一个消息处理成功,消费端就宕机了。发生了
    //    消息丢失。
    //    手动模式下: 只要消费端没有明确签收消息(ack消息) 消息就一直是unacked状态
    // 消费端服务器此时宕机,rabbit服务器端消息也不会丢失，全部变为ready状态，等待下次消费
    //    确认签收消息:在消费端接收Channel channel 管道  channel。basicAck(message.getDeliveryTag(),false);
    // message.getDeliveryTag 消息的标识数据 是管道中设置的 是个自增的 第一个参数 是是否为批量处理
    //    拒绝签收消息:channel.basicNack(long deliveryTay,boolean multiple,boolean requeue)
    // 第一个参数消息id 第一个是否为批处理 第三个是否重新入队列
    // 解决:
    //

    @PostConstruct  //本类对象创建完成之后，执行这个方法
    public void initRabbitTemplate(){
        rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
            /**
             * @Author: SunJinbo
             * @Description
             * @Param correlationData 当前消息的唯一关联数据(这个是消息的唯一id)
             * @Param ack 消息是否成功的收到
             * @Param cause 失败的原因
             * @Param [correlationData, ack, cause]
             * @return void
             * @Data Created in 2022/4/20 20:38
             */
            //rabbit服务器成功收到消息  调用此回调
            @Override
            public void confirm(CorrelationData correlationData, boolean ack, String cause) {
                System.out.println("confim--correlationData:"+correlationData
                        +"ack:"+ack+"cause:"+cause);
            }
        });

        //消息由交换机抵达队列失败 调用此回调
        rabbitTemplate.setReturnsCallback(
                returnedMessage ->
                        System.out.println("当时这个消息用的那个交换机:" +
                                ""+returnedMessage.getExchange()+
                                "当时这个消息用的那个路由键:"+
                                returnedMessage.getRoutingKey()+
                                "回复的文本内容:"+
                                returnedMessage.getReplyText()+
                                "回复的状态码:"+
                                returnedMessage.getReplyCode()+
                                "投递失败的消息的详细信息:"+
                                returnedMessage.getMessage()));
    }
}
